import numpy as np
from .mctspy.tree.nodes import TwoPlayersGameMonteCarloTreeSearchNode
from .mctspy.tree.search import MonteCarloTreeSearch
from .mctspy.games.hex import HexGameState


class RandomPlayer():

    def __init__(self, game):
        self.game = game

    def play(self, board):
        a = np.random.randint(self.game.getActionSize())
        valids = self.game.getValidMoves(board, 1)
        while valids[a] != 1:
            a = np.random.randint(self.game.getActionSize())
        return a


class HumanHexPlayer():

    def __init__(self, game):
        self.game = game

    def play(self, board):
        # display(board)
        valid = self.game.getValidMoves(board, 1)
        # for i in range(len(valid)):
        #     if valid[i]:
        #         print("[",
        #               int(i / self.game.n),
        #               int(i % self.game.n),
        #               end="] ")
        while True:
            input_move = input()
            input_a = input_move.split(" ")
            if len(input_a) == 2:
                try:
                    alphabet = "ABCEDFGHIJK"
                    dic = {}
                    for i, a in enumerate(alphabet):
                        dic[a] = i
                    x, y = dic[input_a[0]], int(input_a[1]) - 1
                    if ((0 <= x) and (x < self.game.n) and (0 <= y) and (y < self.game.n)) or \
                            ((x == self.game.n) and (y == 0)):
                        a = self.game.n * x + y if x != -1 else self.game.n**2
                        if valid[a]:
                            break
                except ValueError:
                    # Input needs to be an integer
                    'Invalid integer'
            print('Invalid move')
        return a


class GreedyHexPlayer():

    def __init__(self, game):
        self.game = game

    def play(self, board):
        valids = self.game.getValidMoves(board, 1)
        candidates = []
        for a in range(self.game.getActionSize()):
            if valids[a] == 0:
                continue
            nextBoard, _ = self.game.getNextState(board, 1, a)
            score = self.game.getGameEnded(nextBoard, 1)
            candidates += [(-score, a)]
        candidates.sort()
        return candidates[0][1]


class MctsHexPlayer():

    def __init__(self, game):
        self.game = game

    def play(self, board):
        s = ""
        for i in range(self.game.n):
            if i > 0:
                s += ","
            for j in range(self.game.n):
                if board[i][j] == 1:
                    s += "R"
                elif board[i][j] == -1:
                    s += "B"
                else:
                    s += "0"
        initial_board_state = HexGameState(state=s,
                                           next_to_move=HexGameState.r)
        root = TwoPlayersGameMonteCarloTreeSearchNode(
            state=initial_board_state)
        mcts = MonteCarloTreeSearch(root)
        move = mcts.best_action(600)
        a = self.game.n * move[0] + move[1]
        return a
